home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume2 / util / wns / wns.c < prev    next >
C/C++ Source or Header  |  1988-10-20  |  13KB  |  526 lines

  1. /* wns.c - Search for string and print window of lines around it.
  2.  
  3.         Nov 19 1984     Mark Mallett   (mem@zinn.MV.COM)
  4.  
  5. mem    860224    Modified to do r/e (regular expression) parsing on unix
  6. mem    860324    Added -f, -n; added code to number lines correctly on
  7.         output.
  8. mem    870325    Added support for regcmp()/regex() style regular expression
  9.         library; redid some conditionals to provide better mix'n'match.
  10. mem    870326    Don't try to print the filename if reading from stdin.
  11.         Add -w option.  Fix a small problem which occasionally allowed
  12.         the separator to come out between adjacent lines of the file.
  13. mem    871119    Fix semantics of call to regcmp(): the NULL terminating the
  14.         argument list was missing.  It worked, but probably only
  15.         due to some bizarre coincidence.
  16.  
  17.     Changes by Mark Rinfret for Amiga (mrr@amanpt1.ZONE1.COM)
  18.  
  19. mrr    881009    Use V8 regexp routines (since I had 'em)
  20.  
  21. */
  22.  
  23. /* The appropriate defines are done in the makefile */
  24. /* #define    OS_UNIX */    /* Define this for unix systems */
  25. /* #define    SYSINC */    /* Define this for sys/ include hierarchy */
  26. /* #define    REGEX */    /* Define this for re_comp/re_exec library */
  27. /* #define    REGCMP */    /* Define this to use regcmp/regex */
  28. /* #define    REGCOMP */    /* Define this to use regcomp/regexec */
  29. /* #define    OS_CPM */    /* Define this for CP/M-80 */
  30.  
  31.  
  32. /* Don't touch these */
  33. #define    NOREGEXP        /* Set this for no regular expression */
  34. #ifdef    REGEX
  35. #undef    NOREGEXP
  36. #endif    REGEX
  37.  
  38. #ifdef    REGCMP
  39. #undef    NOREGEXP
  40. #endif    REGCMP
  41.  
  42. #ifdef REGCOMP
  43. #undef NOREGEXP
  44. #endif
  45.  
  46.  
  47. #ifdef OS_CPM
  48. #include "stdio.h"
  49. #include "ctype.h"
  50. #endif OS_CPM
  51.  
  52. #ifdef OS_UNIX
  53. #include <stdio.h>
  54. #include <ctype.h>
  55.  
  56. #ifdef    SYSINC
  57. #include <sys/types.h>
  58. #include <sys/dir.h>
  59. #else    /* !SYSINC */
  60. #ifndef AMIGA
  61. #include <types.h>
  62. #include <dir.h>
  63. #endif
  64. #endif    SYSINC
  65. #endif OS_UNIX
  66.  
  67. char *calloc();
  68. char *fgets();
  69.  
  70. /* Local definitions */
  71.  
  72. #ifndef    NULL
  73. #define    NULL    ((char *)0)
  74. #endif    NULL
  75.  
  76. #ifndef NUL
  77. #define NUL     '\000'
  78. #endif
  79.  
  80. #ifndef TRUE
  81. #define TRUE    1
  82. #define FALSE   0
  83. #endif
  84.  
  85.  
  86. /* Internal data declared global */
  87.  
  88.  
  89. /* Internal routines */
  90.  
  91.  
  92. /* External data */
  93.  
  94.  
  95. /* External routines */
  96.  
  97. #ifdef    REGEX            /* re_comp/ re_exec */
  98. extern    char    *re_comp();        /* r/e compile */
  99. extern    int    re_exec();        /* r/e exec */
  100. #endif    REGEX
  101.  
  102. #ifdef    REGCMP            /* regcmp/regex */
  103. extern    char    *regcmp();        /* r/e compile */
  104. extern    char    *regex();        /* r/e exec */
  105. #endif    REGCMP
  106.  
  107. #ifdef REGCOMP            /* regcomp/regexec */
  108. extern char    *regcomp();
  109. extern char    *regexec();
  110. #endif
  111.  
  112.  
  113. /* Local data */
  114.  
  115. static  int     Debug={FALSE};          /* Debug enabled flag */
  116. static  int     Lcur = {0};             /* Current line (in Lines array) */
  117. static  char    **Lines = {(char **)NULL};       /* Lines pointer array */
  118. static  int     Linlen = {100};         /* Line length */
  119. static  int     Lone = {0};             /* Line one (in Lines array) */
  120. static    int    Nmr = {0};        /* Number of matched regions */
  121. static  char    *Pat = {NULL};          /* Pattern */
  122. static    char    Shwfile = {TRUE};    /* Show file name... */
  123. static    char    Shwline = {TRUE};    /* Show line number */
  124. static  int     Waft = {0};             /* Window after */
  125. static  int     Wbef = {0};             /* Window before */
  126. static  int     Wsiz = {0};             /* Window size */
  127.  
  128. #ifdef    REGEX        /* regex style r/e manipulations */
  129. char        *Re;        /* Result from re_comp() */
  130. #endif    REGEX
  131.  
  132. #ifdef    REGCMP        /* regcmp style r/e */
  133. char        *Re;        /* Result from regcmp() */
  134. #endif    REGCMP
  135.  
  136. #ifdef REGCOMP
  137. char        *Re;        /* Result from regcomp() */
  138. #endif REGCOMP
  139.  
  140. main (argc, argv)
  141.  
  142. int             argc;           /* Argument count */
  143. char            **argv;         /* Argument values */
  144.  
  145. {
  146. int             i;              /* Scratch */
  147. int             n;              /* Scratch again */
  148. int             c;              /* A character */
  149. char            *aptr;          /* Argument pointer */
  150. int             nf;             /* number of files on command line */
  151.  
  152. nf = 0;                         /* No files on line */
  153.  
  154. for (i = 1; i < argc; i++)      /* Look at args */
  155.     {
  156.     if (argv[i][0] != '-')      /* If option */
  157.         {
  158.         if (Pat == NULL)        /* If no pattern yet given */
  159.         {
  160.             Pat = argv[i];      /*  point here */
  161. #ifdef    REGEX
  162.         if ((Re = re_comp(Pat)) != NULL)
  163.             {
  164.         fprintf(stderr, "wns: %s\n", re);
  165.         exit(1);
  166.         }
  167. #endif    REGEX
  168.  
  169. #ifdef    REGCMP
  170.         if ((Re = regcmp(Pat, NULL)) == NULL)
  171.             {
  172.         fprintf(stderr, "wns: error in regular expression.\n");
  173.         exit(1);
  174.         }
  175. #endif    REGCMP
  176.  
  177. #ifdef    REGCOMP
  178.         if ((Re = regcomp(Pat, NULL)) == NULL)
  179.             {
  180.         fprintf(stderr, "wns: error in regular expression.\n");
  181.         exit(1);
  182.         }
  183. #endif    REGCOMP
  184.  
  185.         }
  186.         else                    /* This must be a file to search */
  187.             {
  188. #ifdef AMIGA
  189.             /* On the Amiga, we may have to do wildcard expansion. */
  190. #ifdef AZTEC_C
  191.             /* Aztec provides a method for this.  I don't know what
  192.              * Lattice provides.  Sorry.
  193.              */
  194.             char *scdir();        /* Aztec C wildcard expansion */
  195.             char *fName;        /* filename back from scdir() */
  196.             int  isWild;
  197.             char testChar;
  198.  
  199.             /* Because the Aztec scdir() routine is so slow (due to 
  200.              * directory scanning), avoid its use if possible.  Only call
  201.              * scdir() if we have a filename with wildcard characters.
  202.              */
  203.             isWild = 0;
  204.             for (fName = argv[i]; testChar = *fName++; )
  205.                 if (testChar == '*' || testChar == '?') {
  206.                     ++isWild;    /* Filename has wildcards. */
  207.                     break;
  208.                 }
  209.  
  210.             if (isWild) {
  211.                 while (fName = scdir(argv[i])) {
  212.                     nf++;
  213.                     dosrch(fName);
  214.                 }
  215.             }
  216.             else {
  217.                 nf++;
  218.                 dosrch(argv[i]);
  219.             }
  220. #else
  221.             /* Lattice variant of wildcard handling goes here. */
  222.             nf++;
  223.             dosrch(argv[i]);
  224. #endif
  225. #else
  226.             nf++;               /* Count it */
  227.             dosrch (argv[i]);   /* Search */
  228. #endif
  229.             }
  230.         }
  231.  
  232.     else                        /* Option char */
  233.         {
  234.         c = argv[i][1];         /* Get option char */
  235.         if (isupper(c))         /* Trap idiot definition of tolower */
  236.             c = tolower(c);     /* Don't care about case */
  237.         n = i;
  238.         aptr = NULL;            /* Find arg, if any */
  239.         if (argv[i][2] != NUL)
  240.             {
  241.             aptr = &argv[i][2];
  242.             n = i;              /* Where to set i if we use this arg */
  243.             }
  244.         else if (i < argc-1)    /* use next.. */
  245.             {
  246.             n = i+1;
  247.             aptr = argv[n];
  248.             }
  249.  
  250.         switch (c)              /* Process the option */
  251.             {
  252.             case 'a':           /* Lines after */
  253.                 Waft = atoi (aptr);
  254.                 Lines = NULL;
  255.                 i = n;
  256.                 break;
  257.  
  258.             case 'b':           /* Lines before */
  259.                 Wbef = atoi (aptr);
  260.                 Lines = (char **)NULL;
  261.                 i = n;
  262.                 break;
  263.  
  264.             case 'd':           /* Enable debugging */
  265.                 Debug = TRUE;
  266.                 break;
  267.  
  268.         case 'f':        /* Suppress filename on output */
  269.             Shwfile = FALSE;
  270.         break;
  271.  
  272.             case 'l':           /* Line length */
  273.                 Linlen = atoi (aptr);
  274.                 Lines = NULL;
  275.                 i = n;
  276.                 break;
  277.  
  278.         case 'n':        /* Suppress line number on output */
  279.             Shwline = FALSE;
  280.         break;
  281.  
  282.             case 'w':           /* Window: lines before and after */
  283.                 Waft = Wbef = atoi (aptr);
  284.                 Lines = NULL;
  285.                 i = n;
  286.                 break;
  287.  
  288.             default:
  289.                 fprintf (stderr, "Invalid option %s\n",argv[i]);
  290.                 exit(1);
  291.             }
  292.         }
  293.     }
  294.  
  295. if ( Pat == NULL )        /* If no pattern given */
  296.     {
  297.     fprintf(stderr, 
  298. "usage: wns [-a n] [-b n] [-d] [-f] [-l n] [-n] [-w n] pattern [filename... ]\n");
  299.     exit(1);
  300.     }
  301.  
  302. if (nf == 0)                    /* No files processed ? */
  303.     dosrch (NULL);              /* Do standard input */
  304.  
  305.     exit(0);
  306. }
  307. /*
  308.  
  309. *//* dosrch (ifnm)
  310.  
  311.         Perform the search
  312.  
  313. Accepts :
  314.  
  315.         ifn             Input file name
  316.  
  317.  
  318. Returns :
  319.  
  320.  
  321. */
  322.  
  323. dosrch (ifnm)
  324.  
  325. char            *ifnm;          /* Input filelname */
  326.  
  327. {
  328. FILE            *ifp;           /* Input fp */
  329. char            *lptr;          /* Line pointer */
  330. int             i;              /* Scratch */
  331. int             prtaft;         /* Print-after count */
  332. int             linnum;         /* Line number */
  333. int        nlb;        /* Number of lines buffered */
  334.  
  335. if (ifnm != NULL)               /* If file name given */
  336.     {
  337.     ifp = fopen (ifnm, "r");    /* Open it for read access */
  338.     if (ifp == NULL)
  339.         {
  340.         fprintf (stderr, "Can not open file %s\n", ifnm);
  341.         return;
  342.         }
  343.     }
  344. else
  345.     ifp = stdin;
  346.  
  347. if (Lines == NULL)              /* If no line table allocated.. */
  348.     {
  349.     Wsiz = Wbef+2;              /* Determine total window size */
  350.     Lines = (char **) calloc (Wsiz, sizeof (char *));
  351.                                 /* Allocate pointer table */
  352.     for (i = 0; i < Wsiz; i++)  /* Allocate line buffers */
  353.         Lines[i] = (char *) calloc (Linlen, sizeof(char));
  354.     }
  355.  
  356. Lcur = Lone = 0;                /* Setup line pointers */
  357. nlb = 0;            /* No lines buffered */
  358. linnum = 0;                     /* Line number is zero */
  359. prtaft = -(Wbef+1);        /* Make sure separator given first time */
  360.  
  361. for (;;)                        /* Loop through the file */
  362.     {
  363.     lptr = Lines[Lcur];         /* Get pointer to current line */
  364.     if (++Lcur == Wsiz)         /* Bump curr pointer and wrap */
  365.         Lcur = 0;               /*  if hit end */
  366.     if (Lone == Lcur)           /* If wrapped to beginning of window */
  367.         if (++Lone == Wsiz)     /*  Bump beginning */
  368.             Lone = 0;           /*   and wrap if hit end */
  369.  
  370.     if (fgets (lptr, Linlen, ifp) != lptr)
  371.         break;                  /*  if end of file */
  372.  
  373.     linnum++;                   /* Count line number */
  374.     if (matlin (lptr))          /* If matching line */
  375.         {
  376.         if (prtaft < (-Wbef) )  /* Check for separator needed */
  377.             if ( (Nmr++ > 0 ) && ((Wbef > 0) || (Waft > 0)) )
  378.                 printf ("-------------------\n");
  379.         while (Lone != Lcur)    /* Until we close the window */
  380.             {
  381.             shwlin (ifnm, linnum-nlb, Lines[Lone]);
  382.                                 /* Show the line */
  383.             if (++Lone == Wsiz)
  384.                 Lone = 0;
  385.         nlb--;
  386.             }
  387.     nlb = 0;        /* No lines buffered */
  388.         prtaft = Waft;          /* Print n lines after */
  389.         }
  390.  
  391.     else                        /* Didn't match */
  392.         {
  393.         if (prtaft-- > 0)       /* If must print lines after */
  394.             {
  395.             shwlin (ifnm, linnum, lptr);
  396.                                 /* Show the line */
  397.             Lone = Lcur;        /* Match pointers */
  398.             }
  399.     else if (nlb < Wbef)    /* Count lines buffered */
  400.         nlb++;
  401.         }
  402.     }
  403.  
  404. if (ifnm != NULL)
  405.     fclose (ifp);
  406. }
  407. /*
  408.  
  409. *//* shwlin (fnm, linnum, line)
  410.  
  411.         Show a matching line
  412.  
  413.  
  414. Accepts :
  415.  
  416.         fnm             File name
  417.  
  418.         linnum          Line number
  419.  
  420.         line            Line to show
  421.  
  422.  
  423. Returns :
  424.  
  425.  
  426. */
  427.  
  428. shwlin (fnm, linnum, line)
  429.  
  430. char            *fnm;           /* File name */
  431. int             linnum;         /* Line number */
  432. char            *line;          /* Line (with newline at end) to print */
  433.  
  434. {
  435. if (Shwfile && ( fnm != NULL) )
  436.     printf("%s%s", fnm, Shwline?" ":":");
  437. if (Shwline)
  438.     printf("@%05d%:", linnum);
  439. printf ("%s", line);
  440. }
  441. /*
  442.  
  443. *//* matlin (line)
  444.  
  445.         Perform match against pattern and line
  446.  
  447.  
  448. Accepts :
  449.  
  450.         line            Address of line to match
  451.  
  452.  
  453. Returns :
  454.  
  455.         <value>         TRUE if match
  456.                         FALSE if not
  457.  
  458.  
  459. */
  460.  
  461.  
  462. int matlin (line)
  463.  
  464. char            *line;          /* Line to match */
  465.  
  466. {
  467. int        rtncode;        /* Return value from this routine */
  468.  
  469.  
  470. #ifdef    NOREGEXP
  471. char            *pptr, *lptr, *tlptr;
  472. int             c1,c2;
  473. #endif    NOREGEXP
  474.  
  475. if (Debug)
  476.     printf ("Matching %s against %s", Pat, line);
  477.  
  478. #ifdef    REGEX
  479. rtncode = re_exec(line);    /* Hand off to r/e evaluator */
  480. #endif    REGEX
  481.  
  482. #ifdef    REGCMP
  483. rtncode = ( regex( Re, line ) != NULL );
  484. #endif    REGCMP
  485.  
  486. #ifdef REGCOMP
  487. rtncode = ( regexec( Re, line ) != NULL );
  488. #endif REGCOMP
  489.  
  490. #ifdef    NOREGEX        /* Have to do menial comparison.. */
  491. lptr = line;                    /* Init line pointer */
  492.  
  493. for ( rtncode = -1; rtncode < 0; )
  494.     {
  495.     tlptr = lptr++;             /* Get temp ptr to line */
  496.     pptr = Pat;                 /* Get ptr to pattern */
  497.     while (TRUE)
  498.         {
  499.         if ((c1 = *pptr++) == NUL)
  500.             {
  501.         rtncode = 1;    /* GOOD return value */
  502.         break;
  503.             }
  504.         if ((c2 = *tlptr++) == NUL)
  505.             {
  506.         rtncode = 0;    /* BAD return value */
  507.         break;
  508.             }
  509.         if (isupper(c1))
  510.             c1 = tolower(c1);
  511.         if (isupper(c2))
  512.             c2 = tolower(c2);
  513.         if (c1 != c2)
  514.             break;
  515.         }
  516.     }
  517. #endif    NOREGEX
  518.  
  519.  
  520. if (Debug)
  521.     printf("matlin returned %s\n", rtncode?"TRUE":"FALSE");
  522. return(rtncode);
  523. }
  524.  
  525.  
  526.